﻿/* *****************************************************************************
 * @ Encoding: UTF-8
 * @ File Name: test.cc
 * @ Author: carl
 * @ Email: naughtygeng@qq.com
 * @ Created Time: 2022-7月-06(星期三) 21:49:57
 * @ All Rights Reserved
 * *****************************************************************************/

#include <iostream>
#include "naughty_differential.hpp"

int main()
{

	// 构造一个数字节点
	auto n = num(3.14);

	std::cout << std::endl;
	// 打印出数字节点
	std::cout << "num(3.245):        " << num(3.245)->to_string() << std::endl;

	// 构造一个自变量节点，该节点为自变量 x
	auto x = var("x");

	// 乘法节点
	auto node_mul = n * x;

	std::cout << std::endl;
	// 打印出乘法节点
	std::cout << "node_mul:        " << node_mul->to_string() << std::endl;

	// 也可以直接这样写
	num(3.14) * var("x");

	// 乘法节点对 自变量x 求导
	auto node_diff = node_mul->differential("x");

	std::cout << std::endl;
	// 打印出上述导数节点
	std::cout << "differential(delta x):        " << node_diff->to_string() << std::endl;

	std::cout << std::endl;
	// 将 自变量x 的值设置为 10, 求出导数节点表达式的值
	double value = node_diff->get_value({{"x", 10}});
	std::cout << "differential value (x=10):        " << value << std::endl;

	std::cout << std::endl;

	// 几个例子：

	std::cout << "Examples: " << std::endl;
	std::cout << std::endl;

	std::cout << "When b = 10        delta(cos(sin((0.5 + b) * (b + b)))) / delta(b)   =        " << cos(sin((num(0.5) + var("b")) *(var("b") + var("b"))))->differential("b")->get_value({{"b", 10}}) << std::endl;

	std::cout << std::endl;

	std::cout << "When c = 10        delta(3.7 * c / (c ^ 2.7)) / delta(c)   =        " << (num(3.7) * var("c") / (var("c")^num(2.7)))->differential("c")->get_value({{"c", 10}}) << std::endl;

	std::cout << std::endl;

	std::cout << "When c = 10        delta(log2(4.3 * c) / (44 + c)) / delta(c)   =        " << (log(num(2), num(4.3) * var("c")) / (num(44) + var("c")))->differential("c")->get_value({{"c", 10}}) << std::endl;

	std::cout << std::endl;

	std::cout << "When x = 10, y = 3        delta(y * x) / dalta(x)   =        " << (var("y") * var("x"))->differential("x")->get_value({{"x", 10}, {"y", 3}}) << std::endl;

	std::cout << std::endl;

	auto n1 = var("E");
	auto n2 = var("R");
	auto n3 = num(1);
	auto n4 = var("t");
	auto n5 = num(-1);
	auto n6 = var("L");

	auto n8 = n1 / n2 * (n3 - exp(n5 * n2 / n6 * n4));

	auto n9 = n8->differential("t");

	naughty_differential::node_optimize(n9);

	std::cout << n9->to_string() << std::endl;

	auto test_sort = var("F") + (var("A") + (var("E") + var("D")) + var("G")) + var("B") * var("C") * var("A") * var("D");

	std::cout << "Before sort:    " << test_sort->to_string() << std::endl;

	naughty_differential::node_sort(test_sort);

	std::cout << "After  sort:    " << test_sort->to_string() << std::endl;

	return 0;
}

